package cn.net.yugu.doraemon.common.jackson;

import java.util.Collection;
import java.util.Map;
import java.util.Optional;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author xiangzhurui
 * @version 2022/12/6 15:21:33
 */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class JacksonUtils {

    private static final ObjectMapper objectMapper = new ObjectMapper();

    static {
        objectMapper.findAndRegisterModules();
    }

    public static Map<String, Object> toMap(Object input) throws JsonProcessingException {
        final String jsonString = objectMapper.writeValueAsString(input);
        final Map<String, Object> map = objectMapper.readValue(jsonString, Map.class);
        return map;
    }

    public static String writeValueAsString(Object object) throws JsonProcessingException {
        return objectMapper.writeValueAsString(object);
    }

    public static Optional<String> writeValueAsStringQuietly(Object object) {
        try {
            final String jsonString = writeValueAsString(object);
            return Optional.ofNullable(jsonString);
        } catch (Throwable e) {
            log.error("input {}", object, e);
            return null;
        }
    }

    /**
     * JSON 反序列化
     * 对象类型的 JSON 都支持
     * 数组类型的 JSON 文本 支持返回数组类型，不支持返回集合（Collection）类型
     *
     * @param json
     * @param type
     * @param <T>
     * @return
     * @throws JsonProcessingException
     * @see #readValue(String, Class, Class) 返回集合类型使用此方法
     */
    public static <T> T readValue(String json, Class<T> type) throws JsonProcessingException {
        if (Collection.class.isAssignableFrom(type)) {
            throw new IllegalStateException("unsupport Collection type [" + type.getCanonicalName() + "]");
        }
        return objectMapper.readValue(json, type);
    }

    public static <T> Optional<T> readValueQuietly(String json, Class<T> type) {
        try {
            final T value = readValue(json, type);
            return Optional.ofNullable(value);
        } catch (Throwable e) {
            log.error("text {} type {} ", json, type, e);
            return Optional.empty();
        }
    }

    /**
     * 解析JSON数组为集合类型
     *
     * @param json           JSON 文本
     * @param collectionType 返回值的集合类型Class
     * @param elementType    集合里的元素类型Class
     * @param <T>            集合类型
     * @param <E>            集合里元素的类型
     * @return
     * @throws JsonProcessingException
     */
    public static <T extends Collection<E>, E> T readValue(String json, Class<T> collectionType, Class<E> elementType)
            throws JsonProcessingException {
        CollectionType type = objectMapper.getTypeFactory().constructCollectionType(collectionType, elementType);
        return objectMapper.readValue(json, type);
    }

    /**
     * 无异常的 解析JSON数组为集合类型
     *
     * @param json
     * @param collectionType
     * @param elementType
     * @param <T>
     * @param <E>
     * @return 解析失败时返回 null
     */
    public static <T extends Collection<E>, E> Optional<T> readValueQuietly(String json, Class<T> collectionType, Class<E> elementType) {
        try {
            final T value = readValue(json, collectionType, elementType);
            return Optional.ofNullable(value);
        } catch (Throwable e) {
            log.error("input json {} collectionType {} elementType {}", json, collectionType, elementType, e);
            return Optional.empty();
        }
    }

    public static <T> T convertValue(Object fromValue, Class<T> toValueType) throws IllegalArgumentException {
        return objectMapper.convertValue(fromValue, toValueType);
    }
}
